package com.soilflow.web.controller.reception.web;

import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.AlgorithmParameterSpec;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.soilflow.common.constant.Constants;
import com.soilflow.common.constant.UserConstants;
import com.soilflow.common.core.domain.AjaxResult;
import com.soilflow.common.core.domain.entity.GamesUserScore;
import com.soilflow.common.core.domain.entity.SysMenu;
import com.soilflow.common.core.domain.entity.SysUser;
import com.soilflow.common.core.domain.entity.SysUserReception;
import com.soilflow.common.core.domain.model.LoginBody;
import com.soilflow.common.core.domain.model.LoginUser;
import com.soilflow.common.core.domain.model.RegisterBody;
import com.soilflow.common.core.redis.RedisCache;
import com.soilflow.common.domain.ColorfulUser;
import com.soilflow.common.utils.MessageUtils;
import com.soilflow.common.utils.NoUtils;
import com.soilflow.common.utils.SecurityUtils;
import com.soilflow.common.utils.StringUtils;
import com.soilflow.framework.manager.AsyncManager;
import com.soilflow.framework.manager.factory.AsyncFactory;
import com.soilflow.framework.web.service.SysLoginService;
import com.soilflow.framework.web.service.SysPermissionService;
import com.soilflow.framework.web.service.TokenService;
import com.soilflow.know.service.GamesUserScoreService;
import com.soilflow.system.service.IColorfulUserService;
import com.soilflow.system.service.ISysMenuService;
import com.soilflow.system.service.ISysUserReceptionService;
import com.soilflow.system.service.ISysUserService;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.util.Base64Utils;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.*;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import static com.soilflow.common.core.domain.AjaxResult.error;
import static com.soilflow.common.core.domain.AjaxResult.success;

/**
 * 登录验证
 *
 * @author relief
 */
@RestController
@RequestMapping("/wx")
public class SysWxLoginController {
    @Autowired
    private SysLoginService loginService;

    @Autowired
    private ISysMenuService menuService;

    @Autowired
    private ISysUserService userService;
    @Autowired
    private IColorfulUserService colorfulUserService;
    @Autowired
    private SysPermissionService permissionService;
    @Autowired
    private ISysUserReceptionService userReceptionService;
    @Autowired
    private GamesUserScoreService gamesUserScoreService;


    /**
     * 登录方法
     *
     * @param loginBody 登录信息
     * @return 结果
     */
    @PostMapping("/login")
    public AjaxResult login(@RequestBody LoginBody loginBody) {
        AjaxResult ajax = success();
        // 生成令牌
        String token = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(),
                loginBody.getUuid());
        ajax.put(Constants.TOKEN, token);
        return ajax;
    }


    @PostMapping("/login/nocode")
    public AjaxResult loginWithoutCaptcha(@RequestBody LoginBody loginBody) {
        AjaxResult ajax = success();
        // 生成令牌
        String token = loginService.loginWithoutCaptcha(loginBody.getUsername(), loginBody.getPassword());
        ajax.put(Constants.TOKEN, token);
        return ajax;
    }

    /**
     * 微信登录方法
     *
     * @param loginBody 登录信息
     * @return 结果
     */
    @PostMapping("/wx/login")
    public AjaxResult wxlogin(@RequestBody LoginBody loginBody) throws Exception {
        AjaxResult ajax = success();
        String token = loginService.wxlogin(loginBody.getUsername()+"_Reception", loginBody.getPassword(), loginBody.getCode(),
                loginBody.getUuid());
        SysUserReception userReception = userReceptionService.getUserInfo(loginBody.getUsername());
        ajax.put(Constants.TOKEN, token);
        ajax.put("userReception",userReception);
        return ajax;
    }
    /**
     * 小程序注册
     */
    @PostMapping("/register")
    public AjaxResult register(@RequestBody RegisterBody registerBody) {
        String msg = "", username = registerBody.getUsername(), phonenumber=registerBody.getPhoneNumber(),password = registerBody.getPassword();
        if (StringUtils.isEmpty(phonenumber)){
            return AjaxResult.error("手机号不能为空");
        }
        //判断手机号是否存在
        SysUserReception userReception = userReceptionService.getPhonenumber(phonenumber);
        if (userReception!=null) {
            return AjaxResult.error("该手机号已经注册过了账号");
        }

         if (StringUtils.isEmpty(username))
        {
            return AjaxResult.error("用户名不能为空");
        }

        if (StringUtils.isEmpty(password))
        {
            return AjaxResult.error("用户密码不能为空");
        }

        if (username.length() < UserConstants.USERNAME_MIN_LENGTH
                || username.length() > UserConstants.USERNAME_MAX_LENGTH)
        {
            return AjaxResult.error("账户长度必须在2到20个字符之间");
        }


       if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
                || password.length() > UserConstants.PASSWORD_MAX_LENGTH)
        {
            return AjaxResult.error("密码长度必须在5到20个字符之间");

        }

        if (UserConstants.NOT_UNIQUE.equals(userReceptionService.checkUserNameUnique(username)))
        {
            return AjaxResult.error("保存用户'" + username + "'失败，注册账号已存在");

        }
            SysUserReception sysUserReception = new SysUserReception();
            sysUserReception.setUserName(username);
            sysUserReception.setCode(NoUtils.getUserCode());
            if (!StringUtils.isEmpty( registerBody.getPhoneNumber()))
            {
                sysUserReception.setPhonenumber(registerBody.getPhoneNumber());
            }
            if (!StringUtils.isEmpty( registerBody.getEmail()))
            {
                sysUserReception.setEmail(registerBody.getEmail());
            }
            sysUserReception.setNickName(username);
            sysUserReception.setPassword(SecurityUtils.encryptPassword(registerBody.getPassword()));
            System.out.println("sysUserReception="+sysUserReception);
            boolean regFlag = userReceptionService.registerUser(sysUserReception);
            if (!regFlag)
            {
                return AjaxResult.error("注册失败,请联系系统管理人员");
            }

        SysUserReception user = userReceptionService.selectUserByUserName(sysUserReception.getUserName());
        GamesUserScore gamesUserScore = new GamesUserScore();
        gamesUserScore.setUserId(user.getUserId());
        gamesUserScore.setLastUpdateTime(new Date());
        gamesUserScore.setScore(BigDecimal.ZERO);
        gamesUserScore.setUserName(user.getUserName());
        gamesUserScoreService.save(gamesUserScore);

        AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.REGISTER,
                        MessageUtils.message("user.register.success")));
            return StringUtils.isEmpty(msg) ? success() : error(msg);
    }


    /**
     * 获取微信小程序登陆用户的电话
     * @return
     * @throws Exception
     */
    @PostMapping("/wx/openid/phone")
    public AjaxResult getOpenIDAndPhone(@RequestBody Map<String, Object> map) throws Exception {
        String appid = "wxdb8d97c4aaf6c441";
        String secret = "3f514c4650e83de2472f36aba67eb5d8";
        String openid = "";
        String sessionKey = "";
        String phone = "";
        String jscode = map.get("jscode").toString();
        String encrypt = map.get("encrypt").toString();
        String iv = map.get("iv").toString();
        String url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + appid +
                "&secret=" + secret + "&js_code=" + jscode + "&grant_type=authorization_code";
        String data = "";
        AjaxResult ajax = success();
    try {
        data = httpGet(url);
        System.out.println("data = " + data);
        JSONObject jsonObject = JSON.parseObject(data);
        sessionKey = jsonObject.getString("session_key");
        openid=jsonObject.getString("openid");
        System.out.println("sessionKey = " + sessionKey);
        phone = getWxMiniPhone(sessionKey, iv, encrypt);
        if (phone != null && !phone.equals("")) {
            ColorfulUser user = colorfulUserService.getPhonenumber(phone);
            if(!ObjectUtils.isEmpty(user)){
                ajax.put(Constants.TOKEN, loginService.loginByUserName(user.getUserName()+"_Duocai"));
                ajax.put("phone", phone);
                ajax.put("userId", user.getUserId());
                ajax.put("users", user);
            }else {
                ColorfulUser colorfulUseruser = new ColorfulUser();
                colorfulUseruser.setPhonenumber(phone);
                colorfulUseruser.setOpenid(openid);
                colorfulUseruser.setNickName(phone);
                colorfulUseruser.setUserName(phone);
                boolean save = colorfulUserService.save(colorfulUseruser);
                if (save) {
                    return success("新增成功");
                }else {
                    return success("新增失败");
                }
            }
        }
        return ajax;
        } catch (Exception e) {
            e.printStackTrace();
            return error("获取手机号异常，请联系管理员");
        }

    }

    /**
     * 获取微信小程序登陆用户的电话2
     * @return
     * @throws Exception
     */
    @PostMapping("/wx2/openid/phone")
    public AjaxResult getOpenIDAndPhone2(@RequestBody Map<String, Object> map) throws Exception {
        String appid = "wx59bc8eca526c8c03";
        String secret = "62ba27a8743695347960b60a8b0e4a07";
        String openid = "";
        String sessionKey = "";
        String phone = "";
        String jscode = map.get("jscode").toString();
        String encrypt = map.get("encrypt").toString();
        String iv = map.get("iv").toString();
        String url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + appid +
                "&secret=" + secret + "&js_code=" + jscode + "&grant_type=authorization_code";
        String data = "";
        AjaxResult ajax = success();
        try {
            data = httpGet(url);
            System.out.println("data = " + data);
            JSONObject jsonObject = JSON.parseObject(data);
            sessionKey = jsonObject.getString("session_key");
            openid=jsonObject.getString("openid");
            System.out.println("sessionKey = " + sessionKey);
            phone = getWxMiniPhone(sessionKey, iv, encrypt);
            if (phone != null && !phone.equals("")) {
                SysUserReception user = userReceptionService.getPhonenumber(phone);

                if(!ObjectUtils.isEmpty(user)){
                    ajax.put(Constants.TOKEN, loginService.loginByUserName(user.getUserName()+"_Reception"));
                    ajax.put("phone", phone);
                    ajax.put("userId", user.getUserId());
                }else {
                    SysUserReception sysUserReception = new SysUserReception();
                    sysUserReception.setPhonenumber(phone);
                    sysUserReception.setNickName(phone);
                    sysUserReception.setUserName(phone);
                    sysUserReception.setCode(NoUtils.getUserCode());
                    boolean save = userReceptionService.registerUser(sysUserReception);

                    if (save) {
                        return success("新增成功");
                    }else {
                        return success("新增失败");
                    }
                }
            }
            return ajax;
        } catch (Exception e) {
            e.printStackTrace();
            return error("获取手机号异常，请联系管理员");
        }

    }


    /*
       Http协议GET请求
      */
    private String httpGet(String url) throws Exception {
        //初始化HttpClient
        CloseableHttpClient httpClient = HttpClients.createDefault();
        //创建HttpGet
        HttpGet httpGet = new HttpGet(url);
        //发起请求，获取response对象
        CloseableHttpResponse response = httpClient.execute(httpGet);
        //获取请求状态码
        //response.getStatusLine().getStatusCode();
        //获取返回数据实体对象
        HttpEntity entity = response.getEntity();
        //转为字符串
        String result = EntityUtils.toString(entity, "UTF-8");
        return result;
    }


    /**
     * 解密电话号
     *
     * @param sessionkey
     * @param iv
     * @param encryptedData
     */
    public static String getWxMiniPhone(String sessionkey, String iv, String encryptedData)
            throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException,
            InvalidKeyException, BadPaddingException, IllegalBlockSizeException, UnsupportedEncodingException {

        byte[] encrypData = Base64Utils.decodeFromString(encryptedData);
        byte[] ivData = Base64Utils.decodeFromString(iv);
        byte[] sessionKey = Base64Utils.decodeFromString(sessionkey);
        String resultString = null;
        AlgorithmParameterSpec ivSpec = new IvParameterSpec(ivData);
        SecretKeySpec keySpec = new SecretKeySpec(sessionKey, "AES");
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
        resultString = new String(cipher.doFinal(encrypData), "UTF-8");
        JSONObject object = JSONObject.parseObject(resultString);
        System.out.println("object = " + object);
        // 拿到手机号码
        String phone = object.getString("phoneNumber");
        return phone;
    }

    /**
     * 获取用户信息
     *
     * @return 用户信息
     */
    @GetMapping("getInfo")
    public AjaxResult getInfo() {
        SysUser user = SecurityUtils.getLoginUser().getUser();
        // 角色集合
        Set<String> roles = permissionService.getRolePermission(user);
        // 权限集合
        Set<String> permissions = permissionService.getMenuPermission(user);
        AjaxResult ajax = success();
        ajax.put("user", user);
        ajax.put("roles", roles);
        ajax.put("permissions", permissions);
        return ajax;
    }

    /**
     * 获取路由信息
     *
     * @return 路由信息
     */
    @GetMapping("getRouters")
    public AjaxResult getRouters() {
        Long userId = SecurityUtils.getUserId();
        List<SysMenu> menus = menuService.selectMenuTreeByUserId(userId);
        return success(menuService.buildMenus(menus));
    }
}
